import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import json
import os
from typing import Dict, Any
import threading
from utils.generator import generate_on_api

class APIConfig:
    """API配置类"""
    def __init__(self):
        self.config_file = "config/settings.json"
        self.default_config = {
            "input_file_path": "",
            "max_tokens": 2000,
            "temperature": 0.2,
            "api_url": "https://api.deepseek.com/v1/",
            "api_key": "",
            "api_type": "deepseek",
            "gen_test_case": True,
            "gen_erl_case": True,
            "gen_document_case": True,
            "gen_json_case": False
        }
        self.load_config()

    def load_config(self):
        """加载配置文件"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    loaded_config = json.load(f)
                    self.default_config.update(loaded_config)
        except Exception as e:
            print(f"加载配置文件失败: {e}")

    def save_config(self, config_data: Dict[str, Any]):
        """保存配置"""
        try:
            result = {}
            for key, var in config_data.items():
                if hasattr(var, 'get'):
                    result[key] = var.get()
                else:
                    result[key] = var
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(result, f, indent=4, ensure_ascii=False)
            self.default_config.update(config_data)
            return True
        except Exception as e:
            print(f"保存配置失败: {e}")
            return False


class APIClient:
    @staticmethod
    def process_file(file_path: str, config: Dict[str, Any], callback_func) -> Dict[str, Any]:
        import time
        str_file_path = file_path.get() if hasattr(file_path, 'get') else file_path     # tk.StringVar数据转str
        result = {}
        for key, var in config.items():
            if hasattr(var, 'get'):
                result[key] = var.get()
            else:
                result[key] = var
        # 检查文件是否存在
        if not os.path.exists(str_file_path):
            return {"status": "error", "message": "文件不存在"}

        generate_on_api(result, callback_func)

        # 模拟API响应
        return {
            "status": "success",
            "message": "文件处理完成",
            "file_path": str_file_path,
            "file_size": os.path.getsize(str_file_path),
            "file_name": os.path.basename(str_file_path),
            "processed_time": time.strftime("%Y-%m-%d %H:%M:%S"),
            "config_used": {
                "api_type": result.get("api_type", "none"),
                "is_gen_test_case": result.get("gen_test_case", False),
                "is_gen_erlang_case": result.get("gen_erl_case", False),
                "is_gen_document_case": result.get("gen_document_case", False),
                "is_gen_json_case": result.get("gen_json_case", False)
            }
        }

class FileProcessorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("测试用例生成工具")
        self.root.geometry("600x700")

        # 初始化配置管理
        self.config_manager = APIConfig()
        self.current_file_path = ""

        # 创建界面
        self.create_widgets()

        # 状态变量
        self.is_processing = False

    def create_widgets(self):
        """创建界面组件"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)

        # 1. 文件选择部分
        file_frame = ttk.LabelFrame(main_frame, text="文件选择", padding="10")
        file_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
        file_frame.columnconfigure(1, weight=1)

        ttk.Button(file_frame, text="选择文件",
                  command=self.select_file).grid(row=0, column=0, padx=(0, 10))

        self.file_path_var = tk.StringVar()
        self.file_path_entry = ttk.Entry(file_frame, textvariable=self.file_path_var,
                                        state='readonly')
        self.file_path_entry.grid(row=0, column=1, sticky=(tk.W, tk.E))

        # 文件信息显示
        self.file_info_label = ttk.Label(file_frame, text="未选择文件")
        self.file_info_label.grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=(5, 0))

        # 2. API调用部分
        api_frame = ttk.LabelFrame(main_frame, text="API调用", padding="10")
        api_frame.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))

        ttk.Button(api_frame, text="调用API处理文件",
                  command=self.call_api, state=tk.NORMAL).grid(row=0, column=0, padx=(0, 10))

        self.api_status_var = tk.StringVar(value="就绪")
        ttk.Label(api_frame, textvariable=self.api_status_var).grid(row=0, column=1, sticky=tk.W)

        # API响应显示
        self.api_response_text = tk.Text(api_frame, height=8, width=60)
        self.api_response_text.grid(row=1, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(10, 0))

        # 添加滚动条
        scrollbar = ttk.Scrollbar(api_frame, orient="vertical",
                                 command=self.api_response_text.yview)
        scrollbar.grid(row=1, column=2, sticky=(tk.N, tk.S))
        self.api_response_text.configure(yscrollcommand=scrollbar.set)

        # 3. 配置部分
        config_frame = ttk.LabelFrame(main_frame, text="配置", padding="10")
        config_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E))
        config_frame.columnconfigure(1, weight=1)

        # 配置项
        config_items = [
            ("需求文档文件路径:", "input_file_path", "str"),
            ("最大输出token:", "max_tokens", "int"),
            ("temperature:", "temperature", "float"),
            ("api_类型:", "api_type", "str"),
            ("api路径:", "api_url", "str"),
            ("api_key:", "api_key", "str"),
            ("生成测试用例", "gen_test_case", "bool"),
            ("生成erlang用例", "gen_erl_case", "bool"),
            ("生成文档补全", "gen_document_case", "bool"),
            ("生成xmind测试用例", "gen_json_case", "bool")
        ]

        self.config_vars = {}

        for i, (label, key, var_type) in enumerate(config_items):
            ttk.Label(config_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
            if var_type == "bool":
                var = tk.BooleanVar(value=self.config_manager.default_config.get(key, False))
                widget = ttk.Checkbutton(config_frame, variable=var)
            else:
                var = tk.StringVar(value=str(self.config_manager.default_config.get(key, "")))
                widget = ttk.Entry(config_frame, textvariable=var)
            if key == "input_file_path":
                self.current_file_path = var
            widget.grid(row=i, column=1, sticky=(tk.W, tk.E), padx=(5, 0), pady=2)
            self.config_vars[key] = var

        # 保存配置按钮
        ttk.Button(config_frame, text="保存配置",
                  command=self.save_config).grid(row=len(config_items), column=0,
                                               columnspan=2, pady=(10, 0))

    def select_file(self):
        """选择文件"""
        file_path = filedialog.askopenfilename(
            title="选择文件",
            filetypes=[
                ("所有文件", "*.*"),
                ("文本文件", "*.txt"),
                ("JSON文件", "*.json"),
                ("Python文件", "*.py")
            ]
        )

        if file_path:
            self.current_file_path = file_path
            self.file_path_var.set(file_path)
            var = self.config_vars["input_file_path"]
            var.set(file_path)
            # 显示文件信息
            file_size = os.path.getsize(file_path)
            file_name = os.path.basename(file_path)
            self.file_info_label.config(
                text=f"文件: {file_name} | 大小: {file_size} 字节"
            )

    def call_api(self):
        """调用API处理文件"""
        if not self.current_file_path:
            messagebox.showwarning("警告", "请先选择文件")
            return

        if self.is_processing:
            messagebox.showinfo("提示", "正在处理中，请稍候...")
            return

        # 在新线程中调用API，避免界面冻结
        self.is_processing = True
        self.api_status_var.set("处理中...")

        thread = threading.Thread(target=self._api_call_thread)
        thread.daemon = True
        thread.start()

    def _api_call_thread(self):
        """API调用的线程函数"""
        try:
            # 清除内容
            self.api_response_text.delete(1.0, tk.END)
            # 获取当前配置
            current_config = self.config_vars

            # 调用API
            result = APIClient.process_file(self.current_file_path, current_config, self._update_api_status)

            # 在主线程中更新UI
            self.root.after(0, self._update_api_result, result)

        except Exception as e:
            error_result = {"status": "error", "message": f"API调用失败: {str(e)}"}
            self.root.after(0, self._update_api_result, error_result)

    def _update_api_status(self, running_status):
        status_text = "处理中..."
        if running_status == "test_cases":
            status_text = "正在处理测试用例..."
        elif running_status == "erlang_cases":
            status_text = "正在处理erlang用例..."
        elif running_status == "document_completion":
            status_text = "正在处理文档补全..."
        elif running_status == "json_cases":
            status_text = "正在处理xmind测试用例"
        self.api_status_var.set(status_text)

    def _update_api_result(self, result):
        """更新API调用结果"""
        self.is_processing = False
        self.api_status_var.set("处理完成")

        # 清空并显示结果
        self.api_response_text.delete(1.0, tk.END)

        if result.get("status") == "success":
            self.api_response_text.insert(tk.END, "✅ API调用成功！\n\n")
            # 格式化显示JSON结果
            formatted_result = json.dumps(result, indent=2, ensure_ascii=False)
            self.api_response_text.insert(tk.END, formatted_result)
        else:
            self.api_response_text.insert(tk.END, "❌ API调用失败！\n\n")
            self.api_response_text.insert(tk.END, f"错误信息: {result.get('message', '未知错误')}")

    def save_config(self):
        """保存配置"""
        try:
            if self.config_manager.save_config(self.config_vars):
                messagebox.showinfo("成功", "配置保存成功！")
            else:
                messagebox.showerror("错误", "配置保存失败！")

        except ValueError as e:
            messagebox.showerror("错误", f"配置值格式错误: {str(e)}")
        except Exception as e:
            messagebox.showerror("错误", f"保存配置时发生错误: {str(e)}")


def main():
    """主函数"""
    root = tk.Tk()
    app = FileProcessorApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()